<?php
class X2CronAction extends CAction {

    public function log($message,$level='trace',$category='application.automation.cron') {
        Yii::log($message,$level,$category);
    }

    public function run(){
        $this->log('Cron request made from '.$_SERVER['REMOTE_ADDR']);
        $t0 = time();    // monitor how long this is taking

        $events = CActiveRecord::model('CronEvent')->findAllBySql(
            'SELECT * from x2_cron_events '.
            'WHERE (recurring=0 AND time < '.time().') OR '.
                '(recurring=1 AND lastExecution < '.time().'-time) '.
            'ORDER BY priority DESC');
        $timeout = Yii::app()->params->admin->batchTimeout;

        $n_events = 0;
        foreach($events as &$event) {
            if(time() - $t0 > $timeout) {    // stop after X seconds, we don't want to time out
                $this->log("Time limit of $timeout seconds reached after processing $n_events ".
                    "X2Flow events.",'error');
                return;
            }
            $n_events++;
            $data = CJSON::decode($event->data);    // attempt to decode JSON data,
            if($data === false) {                    // delete and skip event if it's corrupt
                $this->log("Encountered a corrupt event record that will be deleted (invalid ".
                    "JSON): id={$event->id}, data={$event->data}",'error');
                $event->delete();
                continue;
            }

            if($event->type === 'x2flow') {
                // var_dump($data);
                if(isset($data['flowId'],$data['flowPath'],$data['params'])) {
                    $flow = CActiveRecord::model('X2Flow')->findByPk($data['flowId']);
                    if($flow !== null) {

                        // reload the model into the params array
                        if(isset($data['modelId'],$data['modelClass'])){    
                            $data['params']['model'] = 
                                CActiveRecord::model($data['modelClass'])->
                                    findByPk($data['modelId']);
                            if(is_null($data['params']['model'])){
                                if(!$event->recurring)
                                    $event->delete();    // it was a one-time thing, we're done
                                continue;
                            }
                        }

                        $triggerLogId = null;
                        if (isset ($data['triggerLogId'])) {
                            $triggerLogId = $data['triggerLogId'];
                            $flowTrace = X2Flow::executeFlow(
                                $flow, $data['params'], $data['flowPath'], $triggerLogId);
                            TriggerLog::appendTriggerLog ($triggerLogId, $flowTrace);
                        } else {
                            $flowTrace = X2Flow::executeFlow(
                                $flow, $data['params'], $data['flowPath']);
                        }

                        if(!$event->recurring) {
                            $event->delete();    // it was a one-time thing, we're done
                        }
                    } else {
                        $event->delete();    // flow has been deleted or something
                    }
                } else {
                    $event->delete();    // event is missing parameters
                }
            }
        }
        $t1 = time();
        $t_events = $t1-$t0;
        if($n_events > 0)
            $this->log("Processed $n_events cron events.");

        $criteria = new CDbCriteria();
        // $criteria->addInCondition(array(
        $actionOverdueFlows =
            CActiveRecord::model('X2Flow')->
                findAllByAttributes(array('active'=>true,'triggerType'=>'ActionOverdueTrigger'));

        $n_overdue = 0;
        foreach($actionOverdueFlows as &$flow) {
            $t1_0 = time();
            if($t1_0-$t0 > $timeout) {
                $this->log(
                    "Time limit of $timeout seconds reached after processing $n_events cron ".
                    "events ($t_events seconds) and $n_overdue overdue action X2Flow triggers (".
                    ($t1_0-$t1)." seconds)");
                return;
            }
            $flow = CJSON::decode($flow->flow);
            if($flow === false || !isset($flow['trigger']['type'],$flow['trigger']['options']))
                continue;
            $options = &$flow['trigger']['options'];

            if(!isset($options['duration']['value']))
                continue;
            $time = X2FlowItem::calculateTimeOffset((float)$options['duration']['value'],'secs');

            if($time === false)
                continue;

            $n_overdue++;
            $time = time() - $time;

            $criteria = new CDbCriteria;
            $criteria->addCondition('flowTriggered=0 AND complete != "Yes" AND dueDate < '.$time);
            // var_dump('complete != "Yes" AND dueDate < '.$time);
            $criteria->limit = 100;

            // printR(CActiveRecord::model('Actions')->count($criteria));
            $actions = CActiveRecord::model('Actions')->findAll($criteria);

            foreach($actions as &$action) {
                if(time() - $t0 > $timeout)    // stop; we don't want to time out
                    return;
                $action->flowTriggered=1;
                $action->update(array('flowTriggered'));
                X2Flow::trigger('ActionOverdueTrigger',array(
                    'model'=>$action
                ));
            }
        }
        if($n_overdue > 0) {
            $this->log("Processed $n_overdue overdue action X2Flow triggers in ".(time()-$t1).
            " seconds.");
        }
        // Finally, send unset campaign email using any remaining time:
        Yii::import('application.modules.marketing.controllers.MarketingController');
        $results = MarketingController::sendMail(null,$t0);
        if(isset($results['messages'])) {
            if(is_array($results['messages'])) {
                $this->log(
                    "Ran marketing batch emailer. It responded with these messages:\n".
                    implode("\n",$results['messages']));
            }
        }

    }
}
